﻿namespace Neovolve.Extensibility.ReSharper
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using JetBrains.ReSharper.Psi.CSharp.Tree;
    using JetBrains.ReSharper.Psi.Tree;

    /// <summary>
    /// The <see cref="CommentNodeSetDescriptor"/>
    ///   class is used to describe a set of type references in a comment node.
    /// </summary>
    internal class CommentNodeSetDescriptor : NodeDescriptor
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CommentNodeSetDescriptor"/> class.
        /// </summary>
        /// <param name="node">
        /// The node being described.
        /// </param>
        /// <param name="descriptors">
        /// The descriptors.
        /// </param>
        public CommentNodeSetDescriptor(ITreeNode node, IEnumerable<CommentNodeDescriptor> descriptors)
            : base(node, false)
        {
            Descriptors = descriptors;

            AnalyzeNode();
        }

        /// <summary>
        /// Creates the alias type node.
        /// </summary>
        /// <returns>
        /// A <see cref="ITreeNode"/> value.
        /// </returns>
        public override ITreeNode CreateAliasTypeNode()
        {
            return CreateNewNode(x => x.TypeMapping.AliasTypeName);
        }

        /// <summary>
        /// Creates the CLR type node.
        /// </summary>
        /// <returns>
        /// A <see cref="ITreeNode"/> value.
        /// </returns>
        public override ITreeNode CreateClrTypeNode()
        {
            return CreateNewNode(x => x.TypeMapping.ClrTypeName);
        }

        /// <summary>
        /// Creates the name of the node for type.
        /// </summary>
        /// <param name="typeName">
        /// Name of the type.
        /// </param>
        /// <returns>
        /// A <see cref="ITreeNode"/> value.
        /// </returns>
        protected override ITreeNode CreateNodeForTypeName(String typeName)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Populates the node information.
        /// </summary>
        protected override void PopulateNodeInformation()
        {
            CommentNodeDescriptor firstDescriptor = Descriptors.First();

            IsClrType = firstDescriptor.IsClrType;
            TypeMapping = firstDescriptor.TypeMapping;
        }

        /// <summary>
        /// Creates the new node.
        /// </summary>
        /// <param name="getNewTypeName">
        /// Name of the get new type.
        /// </param>
        /// <returns>
        /// A <see cref="ITreeNode"/> value.
        /// </returns>
        private ITreeNode CreateNewNode(Func<CommentNodeDescriptor, String> getNewTypeName)
        {
            IOrderedEnumerable<CommentNodeDescriptor> descriptors = Descriptors.OrderByDescending(x => x.CommentCaretIndex);
            CommentNodeDescriptor firstDescriptor = descriptors.First();
            String commentText = firstDescriptor.GetCommentText();

            descriptors.ToList().ForEach(x => commentText = x.CreateNewCommentText(commentText, getNewTypeName(x)));

            return CommentNodeDescriptor.CreateNewCommentNode(commentText);
        }

        /// <summary>
        /// Gets the descriptors.
        /// </summary>
        /// <value>
        /// The descriptors.
        /// </value>
        public IEnumerable<CommentNodeDescriptor> Descriptors
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets a value indicating whether the node is supported by this descriptor.
        /// </summary>
        /// <value>
        /// <c>true</c> if the node is supported by this descriptor; otherwise, <c>false</c>.
        /// </value>
        public override Boolean IsSupportedNode
        {
            get
            {
                return Node is IDocCommentNode;
            }
        }
    }
}